﻿//博客：http://www.cnblogs.com/munet
using System;
using System.Collections.Generic;
using System.Data;
using System.Linq;
using System.Text;

namespace Agile.DataAccess
{
    /// <summary>
    /// 数据访问上下文
    /// </summary>
    public interface IDataContext : IDisposable
    {
        /// <summary>
        /// 数据库连接对象
        /// </summary>
        IDbConnection Connection { get; }

        /// <summary>
        /// 执行前输出执行Sql时间
        /// </summary>
        event EventHandler OutputFormatSql;

        /// <summary>
        /// 从指定的配置名称，创建数据库上下文，ConnectionStrings[配置名]，创建DataContext
        /// </summary>
        /// <param name="connectionName">配置名，默认"Default"</param>
        /// <returns></returns>
        IDataContext CreateContext(string connectionName = "Default");

        /// <summary>
        /// 从数据库连接字符串和数据库类型字符串名创建DataContext
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="providerName">数据库类型</param>
        /// <returns></returns>
        IDataContext CreateContext(string connectionString, string providerName);

        /// <summary>
        /// 从数据库连接字符串和数据库类型字符串名创建DataContext
        /// </summary>
        /// <param name="connectionString">连接字符串</param>
        /// <param name="dataProvider">数据库类型</param>
        /// <returns></returns>
        IDataContext CreateContext(string connectionString, Agile.DataAccess.DataProvider dataProvider);

        /// <summary>
        /// 设置执行命令超时时间，单位(秒)
        /// </summary>
        int CommandTimeout { get; set; }

        /// <summary>
        /// 是否忽略自动映射完全匹配
        /// </summary>
        bool IsIgnoreAutoMapFails { get; set; }

        /// <summary>
        ///  执行T-SQL语句
        /// </summary>
        /// <param name="sql">T-SQL语句</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IDbCommand Script(string sql, bool output = true, int commandTimeout = 30);

        /// <summary>
        /// 生成查询语句并填充模型
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IQueryBuilder<T> Builder<T>(bool output = true, int commandTimeout = 30);

        /// <summary>
        /// 根据表名创建查询语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        ISelectBuilder Select(string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据表名创建查询语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        ISelectBuilder<T> Select<T>(string tableName = "", bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据表名创建更新语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IUpdateBuilder Update(string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体创建更新语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IUpdateBuilder<T> Update<T>(T item, string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体创建更新语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IUpdateBuilder<T> Update<T>(T item, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据表名创建插入语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IInsertBuilder Insert(string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体创建插入语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IInsertBuilder<T> Insert<T>(T item, string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体创建插入语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IInsertBuilder<T> Insert<T>(T item, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据表名创建删除语句
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IDeleteBuilder Delete(string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体创建删除语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IDeleteBuilder<T> Delete<T>(T item, string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体创建删除语句
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IDeleteBuilder<T> Delete<T>(T item, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据表名及字段判断数据库记录是否存在
        /// </summary>
        /// <param name="tableName">表名</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IExistsBuilder Exists(string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体判断数据库记录是否存在
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="tableName">表名</param>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IExistsBuilder<T> Exists<T>(T item, string tableName, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 根据实体判断数据库记录是否存在
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认false(不输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IExistsBuilder<T> Exists<T>(T item, bool output = false, int commandTimeout = 30);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <param name="procedureName">存储过程名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IStoredProcedureBuilder Procedure(string procedureName, bool output = true, int commandTimeout = 30);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="procedureName">存储过程名</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IStoredProcedureBuilder<T> Procedure<T>(T item, string procedureName, bool output = true, int commandTimeout = 30);

        /// <summary>
        /// 执行存储过程
        /// </summary>
        /// <typeparam name="T">实体类</typeparam>
        /// <param name="item">实例</param>
        /// <param name="output">是否输出执行脚本,默认true(输出)</param>
        /// <param name="commandTimeout">CommandTimeout超时时间,默认30秒</param>
        /// <returns></returns>
        IStoredProcedureBuilder<T> Procedure<T>(T item, bool output = true, int commandTimeout = 30);

        /// <summary>
        /// 提交事务
        /// </summary>
        /// <returns></returns>
        IDbContext Commit();

        /// <summary>
        /// 回滚事务
        /// </summary>
        /// <returns></returns>
        IDbContext Rollback();

        /// <summary>
        /// 开始事务，此方法执行后必须调用Dispose.
        /// </summary>
        /// <param name="userTransaction"></param>
        /// <returns></returns>
        IDataContext UseTransaction(bool userTransaction = true);

        /// <summary>
        /// 共享数据库连接，此方法执行后必须调用Dispose.
        /// </summary>
        /// <param name="useSharedConnection"></param>
        /// <returns></returns>
        IDataContext UseSharedConnection(bool useSharedConnection = true);

        /// <summary>
        /// 支持返回多个数据集的Command，此方法执行后必须调用Dispose.
        /// </summary>
        /// <returns></returns>
        IDbCommand MultiResultCommand();
    }
}
